from django.db import models
from rest_framework import serializers

from price.models import Price
from resource.models import Resource


# Create your models here.
class Param(models.Model):
    resource = models.ForeignKey(Resource, on_delete=models.PROTECT, verbose_name='资源')  # 资源，外键
    # 土样有关参数
    X1 = models.FloatField(null=True, verbose_name='实测林分有林地土壤侵蚀模数(t·hm⁻²·a⁻¹')
    X2 = models.FloatField(null=True, verbose_name='无林地土壤侵蚀模数(t·hm⁻²·a⁻¹)')
    N_tr = models.FloatField(null=True, verbose_name='实测林分中土壤含氮量(%)')
    P_tr = models.FloatField(null=True, verbose_name='实测林分中土壤含磷量(%)')
    K_tr = models.FloatField(null=True, verbose_name='实测林分中土壤含钾量(%)')
    M_tr = models.FloatField(null=True, verbose_name='实测林分中土壤含有机质量(%)')
    trrz = models.FloatField(null=True, verbose_name='土壤容重(g·cm⁻³)')

    # 林木相关参数
    N_lm = models.FloatField(null=True, verbose_name='实测林木氮元素含量(%)')
    P_lm = models.FloatField(null=True, verbose_name='实测林木磷元素含量(%)')
    K_lm = models.FloatField(null=True, verbose_name='实测林木钾元素含量(%)')
    B_nian = models.FloatField(null=True, verbose_name='(年)实测林分净生产力(t·hm⁻²·a⁻¹)')
    P_s = models.FloatField(null=True, verbose_name='实测林外降水量(mm·a⁻¹)')
    E = models.FloatField(null=True, verbose_name='实测林分年蒸散量(mm·a⁻¹)')
    C = models.FloatField(null=True, verbose_name='实测林分地表快速径流量(mm·a⁻¹)')

    # 固碳释氧
    R_c = models.FloatField(null=True, verbose_name='二氧化碳中碳的含量(27.27%)')
    S_tr = models.FloatField(null=True, verbose_name='单位面积实测林分土壤的固碳量(t·hm⁻²·a⁻¹)')

    # 净化大气环境
    Q_flz = models.FloatField(null=True, verbose_name='实测林分负离子浓度(个·cm⁻³)')
    L = models.FloatField(null=True, verbose_name='负离子寿命(min)')
    Q_SO2 = models.FloatField(null=True, verbose_name='单位面积实测林分吸收二氧化硫量(kg·hm⁻²·a⁻¹)')
    Q_F = models.FloatField(null=True, verbose_name='单位面积实测林分吸收氟化物量(kg·hm⁻²·a⁻¹)')
    Q_NO = models.FloatField(null=True, verbose_name='单位面积实测林分年吸收氮氧化物量(kg·hm⁻²·a⁻¹)')
    Q_TSP = models.FloatField(null=True, verbose_name='实测林分单位面积年滞纳TSP量(kg·hm⁻²·a⁻¹)')
    Q_PM10 = models.FloatField(null=True, verbose_name='实测林分单位叶面积滞纳PM10量(g·m-2)')
    Q_PM25 = models.FloatField(null=True, verbose_name='实测林分单位叶面积滞纳PM2.5量(g·m-2)')
    n = models.IntegerField(null=True, verbose_name='年洗脱次数')
    LAI = models.FloatField(null=True, verbose_name='叶面积指数')

    A_ffgs = models.FloatField(null=True, verbose_name='防风固沙面积(hm²)')
    Y1 = models.FloatField(null=True, verbose_name='有林地风蚀模数(t·hm⁻²·a⁻¹')
    Y2 = models.FloatField(null=True, verbose_name='无林地风蚀模数(t·hm⁻²·a⁻¹)')

    remark = models.CharField(max_length=500, null=True, verbose_name="备注")

    class Meta:
        db_table = 'param'


class ParamSerializer(serializers.ModelSerializer):
    # 资源信息
    province = serializers.StringRelatedField(source='resource.address.province')
    city = serializers.StringRelatedField(source='resource.address.city')
    county = serializers.StringRelatedField(source='resource.address.county')
    town = serializers.StringRelatedField(source='resource.address.town')
    village = serializers.StringRelatedField(source='resource.address.village')

    vegetation_ecological_zone_name = serializers.StringRelatedField(source='resource.vegetation_ecological_zone.name')
    ecological_engineering_zone_name = serializers.StringRelatedField(
        source='resource.ecological_engineering_zone.name')
    ecological_zone_2 = serializers.SerializerMethodField()
    ecological_zone_name = serializers.StringRelatedField(source='resource.ecological_zone.name')
    # ecological_zone_2 = serializers.StringRelatedField(source='resource.ecological_zone_2')
    forest_class_name = serializers.StringRelatedField(source='resource.forest_class.name')
    forest_class_level = serializers.StringRelatedField(source='resource.forest_class.level')
    dominant_tree_species_name = serializers.StringRelatedField(source='resource.dominant_tree_species.name')
    origin_name = serializers.StringRelatedField(source='resource.origin.name')
    age_group_name = serializers.StringRelatedField(source='resource.age_group.name')

    # 保育土壤
    G_gt = serializers.SerializerMethodField()  # G_固土

    G_N = serializers.SerializerMethodField()  # G_N 减少氮流失
    G_P = serializers.SerializerMethodField()  # G_P 减少磷流失
    G_K = serializers.SerializerMethodField()  # G_K 减少钾流失
    G_yjz = serializers.SerializerMethodField()  # G_有机质 减少有机质流失
    G_bf = serializers.SerializerMethodField()  # 保肥

    # 林木养分固持
    G_NL = serializers.SerializerMethodField()  # 氮固持
    G_PL = serializers.SerializerMethodField()  # 磷固持
    G_KL = serializers.SerializerMethodField()  # 钾固持

    # 涵养水源
    G_tiao = serializers.SerializerMethodField()  # G_调，调节水量
    G_jing = serializers.SerializerMethodField()  # G_净，净化水质

    # 固碳释氧
    G_zbgt = serializers.SerializerMethodField()  # G_植被固碳
    G_trgt = serializers.SerializerMethodField()  # G_土壤固碳
    G_yang = serializers.SerializerMethodField()  # G_氧

    # 净化大气环境
    G_flz = serializers.SerializerMethodField()  # G_负离子
    G_SO2 = serializers.SerializerMethodField()  # G_二氧化硫
    G_F = serializers.SerializerMethodField()  # G_氟化物
    G_NO = serializers.SerializerMethodField()  # G_氮氧化物

    G_TSP = serializers.SerializerMethodField()  # G_TSP 滞纳TSP
    G_PM10 = serializers.SerializerMethodField()  # G_PM10 滞纳PM10
    G_PM25 = serializers.SerializerMethodField()  # G_PM25 滞纳PM2.5

    # 防风固沙
    G_ffgs = serializers.SerializerMethodField()  # G_ffgs 防风固沙

    # 价值量评估 ===================================================
    # 保育土壤
    U_gt = serializers.SerializerMethodField()  # U_固土

    # U_N = serializers.SerializerMethodField()  # U_N 减少氮流失
    # U_P = serializers.SerializerMethodField()  # U_P 减少磷流失
    # U_K = serializers.SerializerMethodField()  # U_K 减少钾流失
    # U_yjz = serializers.SerializerMethodField()  # U_有机质 减少有机质流失
    U_bf = serializers.SerializerMethodField()  # 保肥

    # 林木养分固持
    U_NL = serializers.SerializerMethodField()  # 氮固持
    U_PL = serializers.SerializerMethodField()  # 磷固持
    U_KL = serializers.SerializerMethodField()  # 钾固持

    # 涵养水源
    U_tiao = serializers.SerializerMethodField()  # U_调，调节水量
    U_jing = serializers.SerializerMethodField()  # U_净，净化水质

    # 固碳释氧
    U_tan = serializers.SerializerMethodField()  # U_tan，固碳
    U_yang = serializers.SerializerMethodField()  # U_yang，释氧

    # 净化大气环境
    U_flz = serializers.SerializerMethodField()  # U_flz，提供负离子

    U_SO2 = serializers.SerializerMethodField()  # U_二氧化硫
    U_F = serializers.SerializerMethodField()  # U_氟化物
    U_NO = serializers.SerializerMethodField()  # U_氮氧化物

    U_TSP = serializers.SerializerMethodField()  # U_TSP 滞纳TSP

    U_PM10 = serializers.SerializerMethodField()  # U_PM10 滞纳PM10
    U_PM25 = serializers.SerializerMethodField()  # U_PM25 滞纳PM2.5
    U_ffgs = serializers.SerializerMethodField()  # 防风固沙

    class Meta:
        model = Param
        fields = '__all__'

    def get_price(self, name):  # 根据价格名称获取价格
        return Price.objects.get(name=name).value

    def get_ecological_zone_2(self, obj):
        return obj.resource.ecological_zone.name + obj.resource.forest_class.name

    # 价值量评估核算 =============================================
    def get_U_gt(self, obj):
        return round(self.get_G_gt(obj) * self.get_price('C_t') * obj.trrz, 2)

    def get_U_bf(self, obj):
        return round(self.get_G_N(obj) * self.get_price('C1') / self.get_price('R1') +
                     self.get_G_P(obj) * self.get_price('C1') / self.get_price('R2') +
                     self.get_G_K(obj) * self.get_price('C2') / self.get_price('R3') +
                     self.get_G_yjz(obj) * self.get_price('C3'), 2)

    def get_U_NL(self, obj):
        return round(self.get_G_NL(obj) * self.get_price('C1'), 2)

    def get_U_PL(self, obj):
        return round(self.get_G_PL(obj) * self.get_price('C1'), 2)

    def get_U_KL(self, obj):
        return round(self.get_G_KL(obj) * self.get_price('C2'), 2)

    def get_U_tiao(self, obj):
        return round(self.get_G_tiao(obj) * self.get_price('C_k'), 2)

    def get_U_jing(self, obj):
        return round(self.get_G_jing(obj) * self.get_price('K_s'), 2)

    def get_U_tan(self, obj):
        return round((self.get_G_zbgt(obj) + self.get_G_trgt(obj)) * self.get_price('C_C'), 2)

    def get_U_yang(self, obj):
        return round(self.get_G_yang(obj) * self.get_price('C_O'), 2)

    def get_U_flz(self, obj):
        return round(5.256 * (10 ** 15) * obj.resource.area * obj.resource.mean_tree_height *
                     obj.resource.coefficient * self.get_price('K_flz') * (obj.Q_flz - 600) / obj.L, 2)

    def get_U_SO2(self, obj):
        return round(self.get_G_SO2(obj) * self.get_price('K_SO2'), 2)

    def get_U_F(self, obj):
        return round(self.get_G_F(obj) * self.get_price('K_F'), 2)

    def get_U_NO(self, obj):
        return round(self.get_G_NO(obj) * self.get_price('K_NO'), 2)

    def get_U_TSP(self, obj):
        return round(self.get_G_TSP(obj) * self.get_price('K_TSP'), 2)

    def get_U_PM10(self, obj):
        return round(self.get_G_PM10(obj) * self.get_price('K_PM10'), 2)

    def get_U_PM25(self, obj):
        return round(self.get_G_PM25(obj) * self.get_price('K_PM25'), 2)

    def get_U_ffgs(self, obj):
        return round(self.get_G_ffgs(obj) * self.get_price('K_ffgs'), 2)

    # 物质量评估核算 =============================================
    def get_G_gt(self, obj):  # 计算 G_固土
        return round(obj.resource.area * (obj.X2 - obj.X1) * obj.resource.coefficient, 2)

    def get_G_N(self, obj):  # 计算 G_N
        return round(obj.resource.area * obj.N_tr / 100 * (obj.X2 - obj.X1) * obj.resource.coefficient, 2)

    def get_G_P(self, obj):  # 计算 G_P
        return round(obj.resource.area * obj.P_tr / 100 * (obj.X2 - obj.X1) * obj.resource.coefficient, 2)

    def get_G_K(self, obj):  # 计算 G_K
        return round(obj.resource.area * obj.K_tr / 100 * (obj.X2 - obj.X1) * obj.resource.coefficient, 2)

    def get_G_yjz(self, obj):  # 计算 G_yjz
        return round(obj.resource.area * obj.M_tr / 100 * (obj.X2 - obj.X1) * obj.resource.coefficient, 2)

    def get_G_bf(self, obj):  # 计算 G_bf 保肥的总和
        # 调用其他字段的 get 方法获取值并相加
        return round(self.get_G_N(obj) + self.get_G_P(obj) + self.get_G_K(obj) + self.get_G_yjz(obj), 2)

    def get_G_NL(self, obj):  # 计算 G_NL
        return round(obj.resource.area * obj.N_lm / 100 * obj.B_nian * obj.resource.coefficient, 2)

    def get_G_PL(self, obj):  # 计算 G_PL
        return round(obj.resource.area * obj.P_lm / 100 * obj.B_nian * obj.resource.coefficient, 2)

    def get_G_KL(self, obj):  # 计算 G_KL
        return round(obj.resource.area * obj.K_lm / 100 * obj.B_nian * obj.resource.coefficient, 2)

    def get_G_tiao(self, obj):
        return round(10 * obj.resource.area * (obj.P_s - obj.E - obj.C) * obj.resource.coefficient, 2)

    def get_G_jing(self, obj):
        return round(10 * obj.resource.area * (obj.P_s - obj.E - obj.C) * obj.resource.coefficient, 2)

    def get_G_zbgt(self, obj):
        return round(1.63 * obj.R_c * obj.resource.area * obj.B_nian * obj.resource.coefficient, 2)

    def get_G_trgt(self, obj):
        return round(obj.resource.area * obj.S_tr * obj.resource.coefficient, 2)

    def get_G_yang(self, obj):
        return round(1.19 * obj.resource.area * obj.B_nian * obj.resource.coefficient, 2)

    def get_G_flz(self, obj):
        return round(5.256 * (10 ** 15) * obj.Q_flz * obj.resource.area * obj.resource.mean_tree_height * (
                obj.resource.coefficient / obj.L), 2)

    def get_G_SO2(self, obj):
        return round(obj.Q_SO2 * obj.resource.area * (obj.resource.coefficient / 1000), 2)

    def get_G_F(self, obj):
        return round(obj.Q_F * obj.resource.area * (obj.resource.coefficient / 1000), 2)

    def get_G_NO(self, obj):
        return round(obj.Q_NO * obj.resource.area * (obj.resource.coefficient / 1000), 2)

    def get_G_TSP(self, obj):
        return round(obj.Q_TSP * obj.resource.area * (obj.resource.coefficient / 1000), 2)

    def get_G_PM10(self, obj):
        return round(10 * obj.Q_PM10 * obj.resource.area * obj.n * obj.resource.coefficient * obj.LAI, 2)

    def get_G_PM25(self, obj):
        return round(10 * obj.Q_PM25 * obj.resource.area * obj.n * obj.resource.coefficient * obj.LAI, 2)

    def get_G_ffgs(self, obj):
        return round(obj.A_ffgs * (obj.Y2 - obj.Y1) * obj.resource.coefficient, 2)
